import React, {useEffect, useState} from 'react';
import {makeStyles} from "@material-ui/core";
import Image from '../img/bg.jpg'
import TextField from "@material-ui/core/TextField";
import Paper from "@material-ui/core/Paper";
import Typography from "@material-ui/core/Typography";
import Button from "@material-ui/core/Button";
import {useHistory} from "react-router-dom";
import {instance} from "../api";
import Alert from "@material-ui/lab/Alert";
import CircularProgress from "@material-ui/core/CircularProgress";
import {useAuth} from "../contexts/AuthContext";
import * as constants from '../constants'

const useStyles = makeStyles(theme => ({
    root: {
        backgroundImage: `url(${Image})`,
        height: "100vh",
        backgroundPosition: "center",
        backgroundRepeat: "no-repeat",
        backgroundSize: "cover",
        display: "flex",
    },
    paper: {
        maxWidth: "500px",
        height: "600px",
        margin: "auto",
        padding: theme.spacing(8),
        paddingTop: theme.spacing(5),
    },
    form: {
        '& > *': {
            width: "100%",
            marginBottom: theme.spacing(3),
        }
    },
    header: {
        textAlign: "center",
        marginBottom: theme.spacing(3),
    },
    subtitle: {
        marginBottom: theme.spacing(2),
    },
    alert: {
        marginBottom: theme.spacing(3),
    }
}))


// 更改密码时用户必须是登录状态 请求头中必须包含Authorization: Bearer <TOKEN>
const ChangePassword = props => {
    const classes = useStyles()
    const history = useHistory()

    const [loading, setLoading] = useState(false)
    // 变量命名与Django后端保持一致
    const [current_password, setCurrentPassword] = useState('')
    const [new_password, setNewPassword] = useState('')
    const [re_new_password, setReNewPassword] = useState('')
    const [errors, setErrors] = useState({})
    const {isAuthenticated, dispatch} = useAuth()

    const [passwordChanged, setPasswordChanged] = useState(false)

    useEffect(() => {
        // 如果用户是登录后直接修改密码，修改完成后重定向到/login不需要携带next查询参数
        if (passwordChanged)
            history.push('/login')

        // 如果用户没有登录直接访问更改页面重定向到登录页面，登录成功应回到更改密码页面
        if (!isAuthenticated && !passwordChanged)
            history.push('/login?next=/change_password')

    }, [passwordChanged, isAuthenticated, history])


    // 前端校验
    const validate = ({email, password}) => {
        const errors = {}
        if (!current_password) errors.current_password = '当前密码不能为空'
        if (!new_password) errors.new_password = '密码不能为空'
        if (!re_new_password) errors.re_new_password = '确认密码不能为空'

        if (new_password !== re_new_password) {
            // 与后端保持一致
            errors.non_field_errors = '确认密码和密码不匹配'
        }
        return errors
    }

    const handleSubmit = async (e) => {
        e.preventDefault()

        try {
            setErrors({})
            setLoading(true)

            const errors = validate({current_password, new_password, re_new_password})

            // 有错误不往后端提交
            if (Object.keys(errors).length !== 0) {
                setErrors(prevState => ({...prevState, ...errors}))
                setLoading(false)
            } else {
                await instance.post('users/set_password/', {current_password, new_password, re_new_password})
                setLoading(false)
                setPasswordChanged(true)
                dispatch({type: constants.LOGOUT_SUCCESS})

            }
        } catch (e) {
            setLoading(false)

            if (e.response && e.response.status === 400) {
                const data = e.response.data
                // 后端特有的错误
                if (data.hasOwnProperty('non_field_errors'))
                    setErrors({non_field_errors: "确认密码和密码不匹配"})
                else {
                    // 如果有输入，还是返回400错误，说明用户输入的当前密码并不正确
                    if (current_password && data.hasOwnProperty('current_password'))
                        setErrors({'current_password': '当前密码不正确'})
                    else
                        setErrors(data)
                }
            } else if (e.response && e.response.status === 401) {
                setErrors({'detail': '你的登录信息已失效请重新登录'})   // token过期
                dispatch({type: constants.ACCESS_TOKEN_EXPIRED})
            } else {
                setErrors({'detail': '密码重置失败！服务器错误,管理员正在解决...'})
            }
        }
    }

    return (
        <div className={classes.root}>
            <Paper className={classes.paper} elevation={0}>

                {loading && <CircularProgress/>}

                <Typography variant="h3" className={classes.header}>更改密码</Typography>

                {errors.detail && (
                    <Alert severity="error" className={classes.alert}>{errors.detail}</Alert>
                )}

                {errors.non_field_errors && (
                    <Alert severity="error" className={classes.alert}>{errors.non_field_errors}</Alert>
                )}

                <Typography variant="subtitle2" className={classes.subtitle}>
                    请输入当前密码，新的密码和确认密码
                </Typography>
                <form noValidate className={classes.form} onSubmit={handleSubmit}>
                    <TextField
                        error={!!errors.current_password}
                        label="当前密码"
                        variant="outlined"
                        name="current_password"
                        type="password"
                        onChange={e => {
                            setErrors(prevState => ({...prevState, current_password: '', non_field_errors: ''}))
                            setCurrentPassword(e.target.value)
                        }}
                        helperText={!!errors.current_password && errors.current_password}
                    />
                    <TextField
                        error={!!errors.new_password || !!errors.non_field_errors}
                        label="新密码"
                        variant="outlined"
                        name="new_password"
                        type="password"
                        onChange={e => {
                            setErrors(prevState => ({...prevState, new_password: '', non_field_errors: ''}))
                            setNewPassword(e.target.value)
                        }}
                        helperText={!!errors.new_password && errors.new_password}
                    />
                    <TextField
                        error={!!errors.re_new_password || !!errors.non_field_errors}
                        label="确认密码"
                        variant="outlined"
                        name="re_password"
                        type="password"
                        onChange={e => {
                            setErrors(prevState => ({...prevState, re_new_password: '', non_field_errors: ''}))
                            setReNewPassword(e.target.value)
                        }}
                        helperText={!!errors.re_new_password && errors.re_new_password}
                    />
                    <Button variant="contained" color="primary" size="large" type="submit">
                        更改密码
                    </Button>
                </form>
            </Paper>
        </div>
    );
};

export default ChangePassword;












